package sysu.el.graph.undi;

import sysu.el.array.ints.ArrInt;
import sysu.el.graph.Edge;
import sysu.el.graph.GraphConstants;

public class UndiGTAdjListVal extends UndiGTAdjList{

	public int[][] val;

	private UndiGTAdjListVal(){
	}
	
	public UndiGTAdjListVal(int nodeNum) {
		super(nodeNum);
		val = new int[nodeNum][nodeNum];
	}

	public UndiGTAdjListVal(int val[][]){
		this.val = val;
	}

	public void setupEnvWithEdgeList(int edgeNum, Edge[] edgeList){
		int nodeNum = Edge.regulateEdgeList(edgeNum, edgeList) + 1;
		int counter[] = new int[nodeNum];
		for (int i=0; i<edgeNum; i++){
			counter[edgeList[i].s] ++;
			counter[edgeList[i].e] ++;
		}

		for (int i=0; i<nodeNum; i++){
			this.adjNodes[i] = new ArrInt(counter[i]);
			// Notice
			this.val[i] = new int[counter[i]];
		}
	}

	public UndiGTAdjListVal(int edgeNum, Edge[] edgeList){
		super();
		this.setupEnvWithEdgeList(edgeNum, edgeList);
		for (int i=0; i<edgeNum; i++){
			this.addEdge(edgeList[i].s, edgeList[i].e);
		}
	}

	public UndiGTAdjListVal(UndiGTMatrix mat){
		super(mat.getNodeNum());
		for (int i=0; i<this.getNodeNum(); ++i)
			for (int j=i; j<this.getNodeNum(); ++j){
				int w = mat.getW(i, j);
				if (w != GraphConstants.NULL_EDGE){
					// Notice
					val[i][this.getDegree(i)] = w;
					val[j][this.getDegree(j)] = w;
					this.addEdge(i, j);
				}
			}
	}

	public int getVal(int i, int j){
		return val[i][j];
	}

	/* ******************************************************************** */
	/* ******************** Essential Members ***************************** */
	/* ******************************************************************** */
	/**
	 * Make sure you insert the edge from small to big
	 * or invoke sort method.
	 * @param i
	 * @param j
	 * @param val
	 */
	public void insertEdge(int i, int j, int val){
		this.addEdgeVal(i, j, val);
		if (j!=i)
			this.addEdgeVal(j, i, val);
	}

	public void addEdgeVal(int i, int j, int val){
		this.val[i][this.adjNodes[i].counter] = val;
		this.adjNodes[i].add(j);
	}

	/* ******************************************************************** */
	/* *************************** Wrappers ******************************* */
	/* ******************************************************************** */
	
	public static UndiGTAdjListVal wrap(ArrInt[] list, int val[][]){
		UndiGTAdjListVal adj = new UndiGTAdjListVal();
		adj.adjNodes = list;
		adj.val = val;
		adj.edgeNum = UndiGTAdjList.calEdgeNum(list.length, list);
		return adj;
	}
	
	
}
